//
// Created by shaowenhan on 2020/3/1.
//

#ifndef RANDOMNUMBER_RANDOMSEQUENCE_H
#define RANDOMNUMBER_RANDOMSEQUENCE_H
#include "RandomNumber.h"

template <typename val>
class RandomSequence {
private:
    RandomNumber m_randomNumber;
    vector<val> elements;
    int elementsSize;

    void handleElements(int chooseIndex);
public:
    RandomSequence(){}
    void initialElements(vector<val> elements);
    val nextEle();
    bool isRemaining();
    vector<val> randomArrangeElements(vector<val> elements);
    vector<val> generateRandomSequenceWithElesFromLowerToUpper(val lowerBound, val upperBound, val interval=1);
};

template<typename val>
void RandomSequence<val>::initialElements(vector<val> elements) {
    this->elements = elements;
    elementsSize = elements.size();
}

template<typename val>
val RandomSequence<val>::nextEle() {
    if(isRemaining())
    {
        auto randomNumber = m_randomNumber.getRandomNumber(0, elementsSize-1);
        auto res = elements[randomNumber];
        handleElements(randomNumber);
        return res;
    }
    else
        throw "no remaining elements";
}

template<typename val>
void RandomSequence<val>::handleElements(int chooseIndex) {
    swap(elements[chooseIndex], elements[elementsSize-1]);
    elementsSize--;
}

template<typename val>
bool RandomSequence<val>::isRemaining() {
    return elementsSize > 0;
}

template<typename val>
vector<val> RandomSequence<val>::randomArrangeElements(vector<val> elements) {
    vector<val> res(elements);
    for(int i = 0; i < elements.size()-1; i++)
    {
        auto randomNumber = m_randomNumber.getRandomNumber(i, static_cast<int>(elements.size())-1);
        swap(res[randomNumber], res[i]);
    }
    return res;
}

template<typename val>
vector<val>
RandomSequence<val>::generateRandomSequenceWithElesFromLowerToUpper(val lowerBound, val upperBound, val interval) {
    vector<val> res;
    while(lowerBound <= upperBound)
    {
        res.emplace_back(lowerBound);
        lowerBound += interval;
    }
    return randomArrangeElements(res);
}

#endif //RANDOMNUMBER_RANDOMSEQUENCE_H
